package pl.edu.agh.nn.compound;

import java.util.ArrayList;
import java.util.List;

import pl.edu.agh.nn.conf.IOConfiguration;
import pl.edu.agh.nn.conf.InvalidNetworkConfigurationException;
import pl.edu.agh.nn.data.producer.OutputDataProducer;
import pl.edu.agh.nn.data.producer.SimpleDataProducer;
import pl.edu.agh.nn.data.provider.InputDataProvider;
import pl.edu.agh.nn.data.provider.SimpleDataProvider;
import pl.edu.agh.nn.net.AbstractNetWithConfiguration;
import pl.edu.agh.nn.net.INet;
import pl.edu.agh.nn.training.TrainingCaseProvider;

public class CompoundNet implements INet {

	private IOConfiguration ioConfiguration;

	private List<AbstractNetWithConfiguration> nets;

	@Override
	public void compute(InputDataProvider inputDataProvider, OutputDataProducer outputDataProducer) {
		SimpleDataProducer odp = new SimpleDataProducer();
		while (inputDataProvider.hasData()) {
			double data[] = inputDataProvider.nextData();
			for (INet net : nets) {
				net.compute(new SimpleDataProvider(data), odp);
				data = odp.getResult();
			}
			outputDataProducer.produce(data);
		}
		inputDataProvider.finish();
		outputDataProducer.finish();
	}

	@Override
	public IOConfiguration getConfiguration() {
		return ioConfiguration;
	}

	@Override
	public void learn(TrainingCaseProvider trainingCaseProvider) {
		for (INet net : nets) {
			net.learn(net.getConfiguration().getTrainingCaseProvider());
		}
	}

	@Override
	public void configure() throws InvalidNetworkConfigurationException {
		if (nets == null) {
			nets = new ArrayList<AbstractNetWithConfiguration>();
		}
		for (INet net : nets) {
			net.configure();
		}
		ioConfiguration.configure();
	}

}
